/*
* (c) 2014 University of Applied Sciences, Karlsruhe
* Project "Segmentation of depth data of a plenoptic camera"
* summer semester 2014
*
* find_contours_2d.h
* Contains a class which detects contours on a color image.
*/
#ifndef _FIND_CONTOURS_2D_H_
#define _FIND_CONTOURS_2D_H_

#include <vector>

#include <opencv2/opencv.hpp>
#include <Eigen/Dense>

#include "sgBase/geometrics/line_3d.h"
#include "sgMain/2d/contour_2d.h"


using namespace sgBase;
using namespace sgMain;

namespace sgExecution
{
	/**
	The 2D contour detection algorithm. 
	*/
	enum Segmentation3DContourDetectionMethod
	{
		DETECTION_RANSAC, /// RANSAC algorithm, adapted for 2D purpose.
		DETECTION_RANSAC_WITH_QUADTREE, /// RANSAC 2D with an additional quadtree image subdivision.
		DETECTION_HOUGH_TRANSFORM, /// Line detection using the hough transform, model type line.
		DETECTION_SUZUKI_ABE, /// Contour detection using Suzuki-Abe and afterwards contour line approximation
		DETECTION_MANUAL_SELECTION /// Manually select the 2D contours.
	};

	/**
	Class to detect contours in a 2D image and return them as a set of 2D lines.
	*/
	class FindContours2D
	{
	private:
		/**
		The color image onto which the contours are searched.
		*/
		cv::Mat colorImage;

		/**
		A binary edge image of the color image. Created using the Canny edge detector. 
		*/
		cv::Mat edgeImage;
		
		/**
		Flag whether the results of the contour detection should be displayed.
		*/
		bool showResults;

		/**
		Function to find the image contours using the polygonial line approximation.
		*/
		std::vector<Contour2D> FindContoursSuzukiAbe();

		/**
		Function to find the image contours using an adapted version of the RANSAC algorithm to find lines in a binary image.
		*/
		std::vector<Contour2D> FindContoursRANSAC2D();

		/**
		Function to find the image contours using an adapted version of the RANSAC algorithm to find lines in a binary image. To improve the detection
		speed and reduce the number of misdetections, this method subdivides the image using a quadtree method.
		*/
		std::vector<Contour2D> FindContoursRANSAC2DWithQuadtree();

		/**
		Function to find the image contours using the Hough Transform (model line).
		*/
		std::vector<Contour2D> FindContoursHoughTransform();

		/**
		Function to find the image contours using manual point selection.
		*/
		std::vector<Contour2D> FindContoursUsingManualSelection();

		Eigen::Vector2i manualLineSelectionP1; /// Line begin point of currently chosen line in manual selectio mode.
		Eigen::Vector2i manualLineSelectionP2; /// Line end point of currently chosen line in manual selection mode.
		bool manualLineSelectionCurrentPoint; /// Defines whether the begin or the end point of the current line segment is to be defined.
		bool manualLineSelected; /// defines whether at least one line has been selected by the user.
		std::string manualLineSelectionWindowName; /// The name of the window in which the user can select the contours.
		std::vector<Line3D> selectedLines; /// List of lines selected by the user.

		/**
		Event to validate mouse clicks in the manual contour selection window.
		*/
		static void MouseClick(int event, int x, int y, int flags, void *param);

		/**
		Method to update the viewable content of the manual contour selection window.
		*/
		void ManualLineSelectionUpdate();
	public:
		/**
		Constructor.
		\param[in] colorImage The color image.
		\param[in] edgeImage The binary edge image (can be achieved using Canny edge detector).
		\param[in] showResults Defines whether the results should be made visible for the user.
		*/
		FindContours2D(const cv::Mat &colorImage, const cv::Mat &edgeImage, bool showResults);

		/**
		Performs the contour detection algorithm.
		\param[in] method The method to perform the contour detection.
		\param[out] contours The identified 2D contours.
		\return Always 0.
		*/
		int FindContours(Segmentation3DContourDetectionMethod method, std::vector<Contour2D> &contours);
	};
}

#endif